home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 6876 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.8 KB  |  191 lines

  1. Path: news.mira.net.au!news
  2. From: davidw@werple.net.au (David White)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Function returning pointer to equivalent functions
  5. Date: 20 Feb 1996 21:25:40 +1100
  6. Organization: Werple Internet, Melbourne
  7. Message-ID: <4gc7j4$h3s@werple.net.au>
  8. References: <hesterDn1E2r.K1F@netcom.com>
  9. NNTP-Posting-Host: werple.mira.net.au
  10.  
  11. hester@netcom.com (Jim Hester) writes:
  12.  
  13.  
  14. >I want a group of functions that each can return a pointer to any other
  15. >function in that group.  I can't find any direct way to declare the
  16. >function's type since the return type ends up in a "recursive" definition
  17. >loop.  I'd prefer to avoid dirty type changes like using void pointers.
  18.  
  19. >The best that I have done is to envelope the functions in a class and
  20. >return a pointer to the class (example below).  Context: The purpose
  21. >of these functions is to run an automaton.  The main() function below
  22. >demonstrates it's intended control (except the input char, which SHOULD
  23. >be pulled from an input stream).
  24.  
  25. >If states are numbered (as in my unimaginative example below), it's easy
  26. >to have the functions return indices in an array containing pointers to
  27. >all of the functions.  That's the method I've used in the past.  The
  28. >only problem is that I can't use descriptive state names without going
  29. >into manually #defining constants for function locations.
  30.  
  31. >My main question is:
  32. >Can anyone show me a way of directly declaring the functions to return the
  33. >pointer I want?
  34.  
  35. >If not, other suggestions?
  36.  
  37. >If not, can anybody improve what I have below?  The best improvement I
  38. >can think of is a casting operator from FnEnvelope to pFnEnvelope that
  39. >would let me forget about adding the '&'s where I need them below.
  40. >I tried (in public):    operator StateType() {return this;}
  41. >but the compiler didn't like it.
  42.  
  43. >#include <iostream.h>
  44.  
  45. >class FnEnvelope;
  46.  
  47. >typedef StateType (*pStateFn)(char);
  48.  
  49. >class FnEnvelope
  50. >{
  51. >    public:
  52. >    FnEnvelope (StateType (*i_F)(char)) : F(i_F) { }
  53. >    StateType Run(char c) { return (*F)(c); }
  54.  
  55. >    private:
  56. >    StateType (*F)(char);
  57. >};
  58.  
  59. >StateType State1Fn(char);    FnEnvelope State1(State1Fn);
  60. >StateType State2Fn(char);    FnEnvelope State2(State2Fn);
  61. >FnEnvelope StateQuit(NULL);
  62.  
  63. >StateType State1Fn(char c)
  64. >{
  65. >    cout << "this is state1: " << c << endl; // testing
  66. >    switch (c)
  67. >    {
  68. >    case 'e':
  69. >        return &StateQuit;
  70. >    default:
  71. >        return &State2;
  72. >    }
  73. >}
  74.  
  75. >StateType State2Fn(char c)
  76. >{
  77. >    cout << "this is state2: " << c << endl; // testing
  78. >    switch (c)
  79. >    {
  80. >    case 'e':
  81. >        return &StateQuit;
  82. >    default:
  83. >        return &State1;
  84. >    }
  85. >}
  86.  
  87. >void main(void)
  88. >{
  89. >    StateType State;
  90. >    char c = 'a';
  91. >    for ( State = &State1 ; State != &StateQuit ; State = State->Run(c++) );
  92. >}
  93.  
  94.  
  95. An interesting problem. All declarations, no matter how complex, must end
  96. in some type that is not derived from some other, i.e., no matter how
  97. many (), or *, or [] there are in any declaration, it eventually has to
  98. end in something such as 'int', 'char' or 'MyClass'. This fact, as you
  99. have discovered, appears to rule out the possibility of declaring the
  100. type you want directly. I would be tempted to just use a void *, because
  101. it would probably need a cast in only one place. In your example, you
  102. could remove the '&'s, at least where they are :), by using references
  103. instead of pointers, i.e., typedef StateType (&pStateFn)(char);
  104.  
  105. One different approach is demonstrated in the code below. It effectively
  106. replaces your Run() transfer function with a virtual function call.
  107.  
  108. #include <iostream.h>
  109.  
  110. struct Automaton;
  111.  
  112. struct BaseState
  113. {
  114.     BaseState(Automaton &a) : automaton(a) {}
  115.     virtual BaseState *Run(char c) = 0;
  116. protected:
  117.     Automaton &automaton;
  118. };
  119.  
  120. struct State1 : public BaseState
  121. {
  122.     State1(Automaton &a) : BaseState(a) {}
  123.     BaseState *Run(char c);
  124. };
  125.  
  126. struct State2 : public BaseState
  127. {
  128.     State2(Automaton &a) : BaseState(a) {}
  129.     BaseState *Run(char c);
  130. };
  131.  
  132. struct QuitState : public BaseState
  133. {
  134.     QuitState(Automaton &a) : BaseState(a) {}
  135.     BaseState *Run(char c) { return 0; }
  136. };
  137.  
  138. struct Automaton
  139. {
  140.     State1 *state1;
  141.     State2 *state2;
  142.     QuitState *quitState;
  143. };
  144.  
  145.  
  146. BaseState *State1::Run(char c)
  147. {
  148.     cout << "this is state1: " << c << endl; // testing
  149.     switch (c)
  150.     {
  151.     case 'e':
  152.         return automaton.quitState;
  153.     default:
  154.         return automaton.state2;
  155.     }
  156. }
  157.  
  158. BaseState *State2::Run(char c)
  159. {
  160.     cout << "this is state2: " << c << endl; // testing
  161.     switch (c)
  162.     {
  163.     case 'e':
  164.         return automaton.quitState;
  165.     default:
  166.         return automaton.state1;
  167.     }
  168. }
  169.  
  170. int main()
  171. {
  172.     Automaton a;
  173.     State1 state1(a);
  174.     State2 state2(a);
  175.     QuitState quitState(a);
  176.     a.state1 = &state1;
  177.     a.state2 = &state2;
  178.     a.quitState = &quitState;
  179.  
  180.     BaseState *state = &state1;
  181.     char c = 'a';
  182.     while(state)
  183.     {
  184.     state = state->Run(c++);
  185.     }
  186.     return 0;
  187. }
  188.  
  189. David White
  190. davidw@werple.mira.net.au
  191.